package com.lanyou.cook.web;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.entity.domain.Field;
import com.lanyou.cook.entity.domain.FieldSystem;
import com.lanyou.cook.entity.domain.userManagement.User;
import com.lanyou.cook.repository.DBlinkInterfaceRepository;
import com.lanyou.cook.repository.DBlinkRepository;
import com.lanyou.cook.repository.FieldSystemRepository;
import com.lanyou.cook.repository.KettleDataSourceExRepository;
import com.lanyou.cook.repository.SystemInterfaceRepository;
import com.lanyou.cook.repository.userManagement.UserRepository;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.cook.web.param.FieldSystemParam;

/**
 * 领域系统管理相关业务控制层
 * @author 曾族根
 *
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/fieldSystems")
public class FieldSystemController {
	@PersistenceContext
	private EntityManager entityManager;
	@Autowired
	private FieldSystemRepository fieldSystemRepository;
	
	@Autowired
	private UserRepository userRepository;
	
	@Autowired
	private SystemInterfaceRepository systemInterfaceRepository;
	
	@Autowired
	private DBlinkRepository dBlinkRepository;
	
	@Autowired
	private DBlinkInterfaceRepository dBlinkInterfaceRepository;
	
	@Autowired
	private KettleDataSourceExRepository kettleDataSourceExRepository;
	
	/**
	 * 查询特定条件下的领域系统集合
	 * @param param 类型:FieldSystemParam 待查询的领域参数实体
	 * @param pageable 类型:Pageable 待查询的分页参数实体
	 * @return
	 */
	@RequestMapping("/search/findByExample")
	@RequiresPermissions(value = { "fieldSystemManagement:view","fieldSystemManagement:maintain"},logical=Logical.OR)
	public Page<FieldSystem> findByExample(FieldSystemParam param, Pageable pageable) {
		
		Specification<FieldSystem> spec = new Specification<FieldSystem>() {
			@Override
			public Predicate toPredicate(Root<FieldSystem> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicatesList = new ArrayList<>();
				if(StringUtils.isNotBlank(param.getName())){
					predicatesList.add(cb.like(root.get("name"), '%' +param.getName() + '%'));
				}
				
				if(StringUtils.isNotBlank(param.getFieldId())){
					predicatesList.add(cb.equal(root.get("field").get("id"), param.getFieldId()));
				}
				
				/*Path<String> pathOwnerFieldSystemId = root.get("id");
				// 默认查当前登录用户所管理的领域系统
				Collection<String> fieldSystemIds = userSessionService.findFieldSystemIdsOfCurrentAuthenticatedUserCanManage();
				if(!CollectionUtils.isEmpty(fieldSystemIds)){
					predicatesList.add(pathOwnerFieldSystemId.in(fieldSystemIds));
				}*/
				
				query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
				return null;
			}
		};
		
		return fieldSystemRepository.findAll(spec, pageable);
	}
	
	/**
	 * 获取所有的领域系统
	 * @return 类型:List<FieldSystem> 返回一个领域系统集合
	 */
	@RequestMapping("/search/findFieldSystemsByField")
	public String findFieldSystemsByField(String fieldId){
		/*return fieldSystemRepository.findAll();*/
		
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery().distinct(true);
		
		// 构建FROM和JOIN部分
		Root<FieldSystem> rootFieldSystem = cq.from(FieldSystem.class);
		Join<FieldSystem, Field> joinField = rootFieldSystem.join("field");
		/*Join<FieldSystem, User> joinUser = rootFieldSystem.join("users");*/
		
		
		// 构建WHERE部分
		List<Predicate> predicatesList = new ArrayList<>();
		predicatesList.add(cb.equal(joinField.get("id"), fieldId));
		/*predicatesList.add(cb.equal(joinUser.get("userCode"), userCode));*/
		cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
		
		// 构建SELECT部分
		cq.multiselect(rootFieldSystem.get("id").alias("id"), rootFieldSystem.get("name").alias("name"),rootFieldSystem.get("code").alias("code"));

		//cq.orderBy(cb.asc(rootFieldSystem.get("name")));
		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		
		JsonArray jsonDatas = new JsonArray();
		Collator chineseCmp = Collator.getInstance(java.util.Locale.CHINA);
		queryResult.stream()
			.sorted(Comparator.comparing(t -> t.get("name", String.class), chineseCmp))
			.forEach( tuple -> {
				String id = tuple.get("id", String.class);
				String name = tuple.get("name", String.class);
				String code = tuple.get("code",String.class);
				JsonObject jo = new JsonObject();
				jo.addProperty("id", id);
				jo.addProperty("name", name);
				jo.addProperty("code", code);
				jsonDatas.add(jo);
		});
		
		
		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();
	}
	
	/**
	 * 获取当前登录用户所管理的领域系统
	 * @return 类型:String 返回当前登录用户所管理的所有领域系统
	 */
	@RequestMapping(value = "/search/findByFieldOfCurrentUserCanManage", produces = "application/json")
	public String findByFieldOfCurrentUserCanManage(String fieldId) {
		String userCode = UserSessionService.getCurrentAuthenticatedUserCode();
		if (userCode == null)
			throw new UnauthenticatedException();
		
		CriteriaBuilder cb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery().distinct(true);
		
		// 构建FROM和JOIN部分
		Root<FieldSystem> rootFieldSystem = cq.from(FieldSystem.class);
		Join<FieldSystem, Field> joinField = rootFieldSystem.join("field");
		Join<FieldSystem, User> joinUser = rootFieldSystem.join("users");
		
		
		// 构建WHERE部分
		List<Predicate> predicatesList = new ArrayList<>();
		predicatesList.add(cb.equal(joinField.get("id"), fieldId));
		predicatesList.add(cb.equal(joinUser.get("userCode"), userCode));
		cq.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
		
		// 构建SELECT部分
		cq.multiselect(rootFieldSystem.get("id").alias("id"), rootFieldSystem.get("name").alias("name"));

		//cq.orderBy(cb.asc(rootFieldSystem.get("name")));
		// 执行查询
		TypedQuery<Tuple> q = entityManager.createQuery(cq);
		List<Tuple> queryResult = q.getResultList();
		
		JsonArray jsonDatas = new JsonArray();
		Collator chineseCmp = Collator.getInstance(java.util.Locale.CHINA);
		queryResult.stream()
			.sorted(Comparator.comparing(t -> t.get("name", String.class), chineseCmp))
			.forEach( tuple -> {
				String id = tuple.get("id", String.class);
				String name = tuple.get("name", String.class);
				
				JsonObject jo = new JsonObject();
				jo.addProperty("id", id);
				jo.addProperty("name", name);
				jsonDatas.add(jo);
		});
		
		
		JsonObject jsonResult = new JsonObject();
		jsonResult.add("content", jsonDatas);
		return jsonResult.toString();
	}
	@RequestMapping(value = "/search/checkIsCanSave", produces = "application/json")
	public String checkIsCanSave(String name, String code, String originalId) {
		FieldSystem fieldSystem = fieldSystemRepository.findByName(name);
			if (fieldSystem != null) {
			if (!StringUtils.equals(fieldSystem.getId(), originalId)) {
				JsonObject result = new JsonObject();
				result.addProperty("isCanSave", false);
				result.addProperty("errorCode", "DUPLICATE1");
				return result.toString();
			}
		}
			FieldSystem fieldSystem2 = fieldSystemRepository.findByCode(code);
			if (fieldSystem2 != null) {
			if (!StringUtils.equals(fieldSystem2.getId(), originalId)) {
				JsonObject result = new JsonObject();
				result.addProperty("isCanSave", false);
				result.addProperty("errorCode", "DUPLICATE2");
				return result.toString();
			}
		}

		JsonObject result = new JsonObject();
		result.addProperty("isCanSave", true);
		return result.toString();
	}
	
	
	@RequestMapping(value = "/search/checkIsDelete", produces = "application/json")
	public String checkIsDelete(String fieldSystemId) {
		JsonObject result = new JsonObject();
		List<User> userLists = userRepository.findByFieldSystems_Id(fieldSystemId);
		Long i = 0L;
		if(!userLists.isEmpty()){
			for (User user : userLists) {
				if(StringUtils.equals(user.getRoleId(),Constants.FIXED_ROLE_ID_FOR_ADMIN) || StringUtils.equals(user.getRoleId(),Constants.FIXED_ROLE_ID_FOR_IF_ADMIN)){
					i++;
				}
			}
			if(userLists.size() != i){
				result.addProperty("isCanDelete", "EXIST_USER");
				return result.toString();
			}
		}
		
		
		
		Long systemInterfaceIsExist = systemInterfaceRepository.countByOwnerFieldSystem_Id(fieldSystemId);
		if(systemInterfaceIsExist != 0){
			result.addProperty("isCanDelete", "EXIST_INTERFACE");
			return result.toString();
		}
		
		Long dbLinkIsExist = dBlinkRepository.countByFieldSystem_Id(fieldSystemId);
		if(dbLinkIsExist != 0){
			result.addProperty("isCanDelete", "EXIST_DBLINK");
			return result.toString();
		}
		
		Long dBlinkInterfaceIsExist = dBlinkInterfaceRepository.countByFieldSystem_Id(fieldSystemId);
		if(dBlinkInterfaceIsExist != 0){
			result.addProperty("isCanDelete", "EXIST_DBLINK_INTERFACE");
			return result.toString();
		}
		Long kettleDataSourceExIsExist = kettleDataSourceExRepository.countByFieldSystem_Id(fieldSystemId);
		if(kettleDataSourceExIsExist != 0){
			result.addProperty("isCanDelete", "EXIST_KETTLE_DATASOURCE");
			return result.toString();
		}
		
		result.addProperty("isCanDelete", true);
		return result.toString();
	}
	
}
